package main

import (
	"fmt"
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/ethclient"
	"github.com/ethereum/go-ethereum/rpc"
	"io/ioutil"
	"log"
	"main/Learn_Go/contract"
	"os"
	"strings"
)

var contractAddr = "0xA3Ba0907Add612217A371c8E23d87986C488b84a"
var dir = "E:\\BlockChian\\devdata\\keystore"

func main() {
	var commd, pass string
	cli, err := ethclient.Dial("http://localhost:8545")
	if err != nil {
		fmt.Println("err======", err)
	}
	for {
		fmt.Println("请问您需要那种服务呢？\n" +
			"1.创建账户\n" +
			"2.注册solidity账号\n" +
			"3.修改密码\n" +
			"4.登录账号\n" +
			"5.退出")
		fmt.Scanf("%s", &commd)

		if commd == "1" {
			fmt.Println("开始创建账户")
			fmt.Println("请输入您的密码")
			fmt.Scanf("%s", &pass)
			NewAcc(pass)
		} else if commd == "2" {
			CreatAccount(cli)
		} else if commd == "3" {
			ChangePass(cli)
		} else if commd =="4"{
			Login(cli)
		}else if commd == "5"{
			cli.Close()
			break
		}else {
			fmt.Printf("不能输入%d,请输入1/2", commd)
		}


	}
}
func NewAcc(pass string) {
	cli, err := rpc.Dial("http://localhost:8545")
	if err != nil {
		log.Fatal("fail to connect the geth", err)

	}
	defer cli.Close()
	var account string
	err = cli.Call(&account, "personal_newAccount", pass)
	if err != nil {
		log.Fatal("fail to new account personal !!!", err)

	}
	fmt.Println("account ====== ", account)
}
func CreatAccount(clie *ethclient.Client) {
	var pass, account, name,passWord string
	function, err := contract.NewApiname(common.HexToAddress(contractAddr), clie)
	if err != nil {
		log.Fatal("fail to use funtion !!!", err)
	}
	fmt.Println("请输入您的账户")
	fmt.Scanf("%s", &account)
	fmt.Println("请输入您的密码")
	fmt.Scanf("%s", &pass)
	opts, err := GetOpts(account, dir, pass)
	if err != nil {
		fmt.Println("ERR===", err)
	}
	fmt.Println("请输入您要创建的姓名!")
	fmt.Scanf("%s", &name)
	fmt.Println("请输入您要创建的密码!")
	fmt.Scanf("%s", &passWord)

	_, err = function.CreatUser(opts, name,passWord)
	if err != nil {
		fmt.Println("err====", err)
	}
}
func ChangePass(clie *ethclient.Client)  {
	var pass, account,name , Opass , Npass string;
	function, err := contract.NewApiname(common.HexToAddress(contractAddr), clie)
	if err != nil {
		log.Fatal("fail to use funtion !!!", err)
	}
	fmt.Println("请输入您区块链的账户")
	fmt.Scanf("%s", &account)
	fmt.Println("请输入您区块链的密码")
	fmt.Scanf("%s", &pass)
	fmt.Println("请输入您的姓名")
	fmt.Scanf("%s", &name)
	fmt.Println("请输入您旧的密码")
	fmt.Scanf("%s", &Opass)
	fmt.Println("请输入您新的密码")
	fmt.Scanf("%s", &Npass)
	opts, err := GetOpts(account, dir, pass)
	if err != nil {
		fmt.Println("ERR===", err)
	}
	_, err = function.ChangePass(opts, name,Opass,Npass)
	if err != nil {
		fmt.Println("err====", err)
	}
}
func Login(clie *ethclient.Client){
	var Bpass, account,name , pass string;
	function, err := contract.NewApiname(common.HexToAddress(contractAddr), clie)
	if err != nil {
		log.Fatal("fail to use funtion !!!", err)
	}
	fmt.Println("请输入您区块链的账户")
	fmt.Scanf("%s", &account)
	fmt.Println("请输入您区块链的密码")
	fmt.Scanf("%s", &Bpass)
	fmt.Println("请输入您的姓名")
	fmt.Scanf("%s", &name)
	fmt.Println("请输入您的密码")
	fmt.Scanf("%s", &pass)
	opts, err := GetOpts(account, dir, pass)
	if err != nil {
		fmt.Println("ERR===", err)
	}
	_, err = function.Login(opts, name,pass)
	if err != nil {
		fmt.Println("err====", err)
	}

}
func GetOpts(addr string, dirname string, pass string) (*bind.TransactOpts, error) {
	ks, err := GetFileContent(addr, dirname)
	if err != nil {
		log.Fatal("fail to access the key")

	}
	opts, err := bind.NewTransactor(strings.NewReader(ks), pass)
	if err != nil {
		log.Fatal("fail to read the file")
		return nil, err
	}
	return opts, err

}
func GetFileContent(address, dirname string) (string, error) {
	data, err := ioutil.ReadDir(dirname) 
	if err != nil {
		fmt.Println("read dir err", err)
		return "", err
	}
	for _, v := range data {
		if strings.Index(strings.ToLower(v.Name()), strings.ToLower(address)[2:]) > 0 {
			//代表找到文件
			file, err := os.Open(dirname + "\\" + v.Name())
			if err != nil {
				fmt.Printf("Failed to open file %v, err === %v\n", v.Name(), err)
				return "", err
			}
			data := make([]byte, 1024)
			count, err := file.Read(data)
			if err != nil || count < 1 {
				fmt.Printf("Failed to read file %v, err === %v\n", v.Name(), err)
				return "", err
			}
			return string(data[:count]), nil
		}
	}
	return "", nil
}
